﻿#include "calculator2.h"
#include "ui_calculator2.h"

calculator2::calculator2(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::calculator2)
{
    ui->setupUi(this);

//    connect(this->ui->pushButton_0,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_0_clicked()));
//    connect(this->ui->pushButton_1,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_1_clicked()));
//    connect(this->ui->pushButton_2,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_2_clicked()));
//    connect(this->ui->pushButton_3,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_3_clicked()));
//    connect(this->ui->pushButton_4,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_4_clicked()));
//    connect(this->ui->pushButton_5,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_5_clicked()));
//    connect(this->ui->pushButton_6,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_6_clicked()));
//    connect(this->ui->pushButton_7,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_7_clicked()));
//    connect(this->ui->pushButton_8,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_8_clicked()));
//    connect(this->ui->pushButton_9,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_9_clicked()));
//    connect(this->ui->pushButton_add,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_add_clicked()));
//    connect(this->ui->pushButton_sub,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_sub_clicked()));
//    connect(this->ui->pushButton_mul,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_mul_clicked()));
//    connect(this->ui->pushButton_div,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_div_clicked()));
//    connect(this->ui->pushButton_equal,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_equal_clicked()));
//    connect(this->ui->pushButton_clear,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_clear_clicked()));
//    connect(this->ui->pushButton_point,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_point_clicked()));
//    connect(this->ui->pushButton_del,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_del_clicked()));
//    connect(this->ui->pushButton_right,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_right_clicked()));
//    connect(this->ui->pushButton_left,SIGNAL(clicked(bool)),this,SLOT(on_pushButton_left_clicked()));
    exp="";
    m_result="";
    m_exp="";
}

calculator2::~calculator2()
{
    delete ui;
}

void calculator2::on_pushButton_0_clicked()
{
   exp+=ui->pushButton_0->text();
   this->ui->label->setText(exp);
}

void calculator2::on_pushButton_1_clicked()
{
    exp+=ui->pushButton_1->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_2_clicked()
{
    exp+=ui->pushButton_2->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_3_clicked()
{
    exp+=ui->pushButton_3->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_4_clicked()
{
    exp+=ui->pushButton_4->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_5_clicked()
{
    exp+=ui->pushButton_5->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_6_clicked()
{
    exp+=ui->pushButton_6->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_7_clicked()
{
    exp+=ui->pushButton_7->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_8_clicked()
{
    exp+=ui->pushButton_8->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_9_clicked()
{
    exp+=ui->pushButton_9->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_add_clicked()
{
    exp+=ui->pushButton_add->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_sub_clicked()
{
    exp+=ui->pushButton_sub->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_mul_clicked()
{
    exp+=ui->pushButton_mul->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_div_clicked()
{
    exp+=ui->pushButton_div->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_clear_clicked()
{
    exp="";
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_del_clicked()
{
   exp=exp.left(exp.length()-1);
   this->ui->label->setText(exp);
}

void calculator2::on_pushButton_right_clicked()
{
    exp+=ui->pushButton_right->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_left_clicked()
{
    exp+=ui->pushButton_left->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_point_clicked()
{
    exp+=ui->pushButton_point->text();
    this->ui->label->setText(exp);
}

void calculator2::on_pushButton_equal_clicked()
{
     m_exp=exp;
     exp="";
     this->ui->label->setText(exp);
     expression(m_exp);
     result();
     this->ui->label->setText(m_result);
     exp=result();
}

bool calculator2::isOperator(QString s)
{
    return(s=="+")||(s=="-")||(s=="*")||(s=="/");
}

QQueue<QString> calculator2::split(QString& m_exp)
{
    QQueue<QString> ret;
    QString num="";
    QChar pre;
    QChar c;
    for(int i=0;i<m_exp.length();i++)
    {
       c=m_exp[i];
       if((('0'<=c)&&(c<='9'))||(c=='.'))
       {
           num+=c;
           pre=c;
       }
       else if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')')
       {
           if(!num.isEmpty())
           {
               ret.enqueue(num);
               num.clear();
           }
           if((c=='+'||c=='-')&&((pre==' ')||(pre=='(')||(pre=='+')||(pre=='-')||(pre=='*')||(pre=='/')))
           {
               num+=c;
           }
           else
           {
               ret.enqueue(c);
           }
           pre=c;
       }
    }
    if(!num.isEmpty())
    {
        ret.enqueue(num);
    }
return ret;
}

int calculator2::priority(QString s)
{
    int ret=0;
    if((s=="+")||(s=="-"))
        ret=1;
    if((s=="*")||(s=="/"))
        ret=2;
    return ret;
}

bool calculator2::math(QQueue<QString>& m_exp)
{
    bool ret=true;
    QStack<QString> stack;
    for(int i=0;i<m_exp.length();i++)
    {
        if(m_exp[i]=="(")
        {
            stack.push(m_exp[i]);
        }
        else if(m_exp[i]==")")
        {
            if(!stack.isEmpty()&&stack.top()=="(")
            {
                stack.pop();
            }
            else
            {
                ret=false;
                break;
            }
        }
    }
    return ret && stack.isEmpty();
}

bool calculator2::isNumber(QString s)
{
    bool ret=false;
    s.toDouble(&ret);//转换成double型数，如果转换成功则返回true
    return ret;
}

bool calculator2::transform(QQueue<QString>& m_exp,QQueue<QString>& output)
{
    bool ret=math(m_exp);
    QStack<QString> stack;
    output.clear();
    while(ret && !m_exp.isEmpty())
    {
        QString e=m_exp.dequeue();
        if(isNumber(e))
        {
            output.enqueue(e);
        }
        else if(isOperator(e))
        {
            while(!stack.isEmpty() && (priority(e)<=priority(stack.top())))
            {
                output.enqueue(stack.pop());
            }
            stack.push(e);
        }
        else if(e=="(")
        {
            stack.push(e);
        }
        else if(e==")")
        {
            if(!stack.isEmpty() && stack.top()!="(")
            {
                output.enqueue(stack.pop());
            }
            if(!stack.isEmpty())
            {
                stack.pop();
            }
        }
        else
        {
            ret=false;
        }
    }
    while(!stack.isEmpty())
    {
        output.enqueue(stack.pop());
    }
    if(!ret)
    {
        output.clear();
    }
    return ret;
}

QString calculator2::calculator(QString lp,QString op,QString rp)
{
    QString ret="error";
    if(isNumber(lp) && isNumber(rp))
    {
        double l=lp.toDouble();
        double r=rp.toDouble();
        if(op=="+")
        {
            ret.sprintf("%f",l+r);
        }
        else if(op=="-")
        {
            ret.sprintf("%f",l-r);
        }
        else if(op=="*")
        {
            ret.sprintf("%f",l*r);
        }
        else if(op=="/")
        {
            if(r==0)
            {
                ret="error";
            }
            else
            {
               ret.sprintf("%f",l/r);
            }
        }
        else
        {
            ret="error";
        }
    }
    return ret;
}

QString calculator2::calculator(QQueue<QString>& m_exp)
{
    QString ret = "Error";
    QStack<QString> stack;

    while(!m_exp.isEmpty())
    {
        QString e = m_exp.dequeue();

        if( isNumber(e) )
        {
            stack.push(e);
        }
        else if(isOperator(e))
        {
            if( !stack.isEmpty() )
            {
                QString rp = stack.pop();
                QString lp = stack.pop();

                QString result = calculator(lp, e, rp);

                if(result != "Error")
                {
                    stack.push(result);
                }
                else
                {
                    break;
                }
            }
        }
        else
        {
            break;
        }
    }
    if(!stack.isEmpty() && stack.size() == 1 && isNumber(stack.top()))
    {
        ret = stack.pop();
    }
    return ret;
}

bool calculator2::expression(QString& m_exp)
{
    bool ret=false;
    QQueue<QString> spExp = split(m_exp);
    QQueue<QString> posExp;

    exp = m_exp;

    if(transform(spExp, posExp))
    {
        m_result = calculator(posExp);

        ret = (m_result != "Error");
    }
    else
    {
        m_result = "Error";
    }
    return ret;
}

QString calculator2::result()
{
    return m_result;
}
